package cn.uway.config;

import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.DelegatingFilterProxy;

import cn.uway.cache.LocalCache;
import cn.uway.properties.ShiroProperties;
import cn.uway.shiro.DatabaseRealm;
import cn.uway.shiro.MyEhcacheManager;


@Configuration
public class ShiroConfiguration {
	
	protected  Logger logger = LoggerFactory.getLogger(this.getClass());
	
	/**
     * 注册DelegatingFilterProxy（Shiro）
     */
    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
        //  该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理  
        filterRegistration.addInitParameter("targetFilterLifecycle", "true");
        filterRegistration.setEnabled(true);
        filterRegistration.addUrlPatterns("/*");
        return filterRegistration;
    }
    
    @Bean
    public  HashedCredentialsMatcher credentialsMatcher(){
    	HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
    	credentialsMatcher.setHashAlgorithmName("md5");
    	credentialsMatcher.setHashIterations(2);
    	return credentialsMatcher;
    }
      

    @Bean(name = "databaseRealm")
    public DatabaseRealm databaseRealm(HashedCredentialsMatcher credentialsMatcher) {  
    	DatabaseRealm realm = new DatabaseRealm(credentialsMatcher); 
        return realm;
    } 
    
    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
        daap.setProxyTargetClass(true);
        return daap;
    }

    
	@Bean
    public MyEhcacheManager<String,Object>  shiroCacheManager(net.sf.ehcache.CacheManager ehcacheManager,LocalCache ehcache) {  
     	MyEhcacheManager<String,Object>  em = new MyEhcacheManager<String,Object>(ehcacheManager, ehcache);  
        return em;  
    }  
	 
	 
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager securityManager(DatabaseRealm databaseRealm, MyEhcacheManager<String,Object> shiroCacheManager) {
        DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
        dwsm.setRealm(databaseRealm);
        //用户授权/认证信息Cache
        dwsm.setCacheManager(shiroCacheManager);        
        return dwsm;
    }
    
    @Bean
    public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
        aasa.setSecurityManager(securityManager);
        return aasa;
    }
 
    
    @Bean
    public  ShiroFilterFactoryBean  shiroFilter(DefaultWebSecurityManager securityManager, @Autowired ShiroProperties shiroProperties) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 必须设置 SecurityManager  
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
        shiroFilterFactoryBean.setLoginUrl(shiroProperties.getLoginUrl());  
        // 登录成功后要跳转的连接
        shiroFilterFactoryBean.setSuccessUrl(shiroProperties.getSuccessUrl());
        shiroFilterFactoryBean.setUnauthorizedUrl(shiroProperties.getLoginUrl());          
        
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); 
        String anonUrls = shiroProperties.getAnonUrls();       
        if(!StringUtils.isEmpty(anonUrls)){
        	String[] array = anonUrls.split(",");
        	for(String anonUrl : array){
        		anonUrl = anonUrl.trim();
        		if(!"".equals(anonUrl)){
        			  filterChainDefinitionMap.put(anonUrl, "anon");
        		}
        	}
        }
        String authcUrls = shiroProperties.getAuthcUrls();
        if(!StringUtils.isEmpty(authcUrls)){
        	String[] array = authcUrls.split(",");
        	for(String authcUrl : array){
        		authcUrl = authcUrl.trim();
        		if(!"".equals(authcUrl)){
        			  filterChainDefinitionMap.put(authcUrl, "authc");
        		}
        	}
        }
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        logger.debug("==============shiroFilterFactoryBean.loginUrl={}", shiroProperties.getLoginUrl());
    	logger.debug("==============shiroFilterFactoryBean.successUrl={}"+shiroProperties.getSuccessUrl());       
        logger.debug("==============shiroFilterFactoryBean.filterChainDefinitionMap={}",filterChainDefinitionMap); 
        
        return shiroFilterFactoryBean;
    }
    
}
